package com.zgw.fireline.design.edit;

import java.lang.reflect.Method;
import java.util.Date;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.wb.core.model.JavaInfo;
import org.eclipse.wb.core.model.ObjectInfo;
import org.eclipse.wb.internal.core.DesignerPlugin;
import org.eclipse.wb.internal.core.model.description.ComponentDescription;
import org.eclipse.wb.internal.core.model.nonvisual.NonVisualBeanContainerInfo;
import org.eclipse.wb.internal.core.model.util.ObjectsLabelProvider;
import org.eclipse.wb.internal.core.model.variable.VariableSupport;
import org.eclipse.wb.internal.core.utils.execution.ExecutionUtils;
import org.eclipse.wb.internal.core.utils.execution.RunnableEx;
import org.eclipse.wb.internal.core.utils.reflect.ReflectionUtils;
import org.eclipse.wb.internal.core.utils.ui.GridDataFactory;
import org.eclipse.wb.internal.core.utils.ui.GridLayoutFactory;
import org.eclipse.wb.internal.core.utils.ui.UiUtils;
import org.eclipse.wb.internal.rcp.databinding.ui.providers.TypeImageProvider;
import org.eclipse.wb.internal.swt.model.widgets.WidgetInfo;
import org.eclipse.wb.swt.ResourceManager;

import com.ibm.icu.text.SimpleDateFormat;
import com.zgw.fireline.design.Activator;
import com.zgw.fireline.design.Model.DatasetInfo;
import com.zgw.fireline.design.common.ExecutionUtils2;

public class ParamDialog extends TitleAreaDialog {

	private JavaInfo root;
	private Tree treeComponent;
	private Tree treeProperty;
	private static final String[] WIDGET_PROPERTIES_METHODS = {
			"getBackground()", "getBounds()", "getEditable()", "getEnabled()",
			"isFocusControl()", "getFont()", "getForeground()", "getImage()",
			"getLocation()", "getMaximum()", "getMessage()", "getMinimum()",
			"getSelectionIndex()", "getSize()", "getToolTipText()",
			"isVisible()", "getItems()", "getSelection()", "getText()",
			"getText(int)", "getText(int[])" };

	public Param param;
	private Text valueText;
	private Class<?> type;
	private String format;

	/**
	 * Create the dialog.
	 * 
	 * @param parentShell
	 */
	public ParamDialog(Shell parentShell, JavaInfo root) {
		super(parentShell);
		setShellStyle(SWT.MAX | SWT.RESIZE);
		setBlockOnOpen(false);
		setHelpAvailable(false);
		setBlockOnOpen(true);
		this.root = root;
	}

	/**
	 * Create contents of the dialog.
	 * 
	 * @param parent
	 */
	@Override
	protected Control createDialogArea(Composite parent) {
		setMessage("录入获指定一个控件属性做为参数值。");
		setTitle("参数值编辑");
		Composite area = (Composite) super.createDialogArea(parent);

		SashForm sashForm = new SashForm(area, SWT.NONE);
		GridData gd_sashForm = new GridData(SWT.FILL, SWT.FILL, true, true, 1,
				1);
		gd_sashForm.verticalIndent = -1;
		sashForm.setLayoutData(gd_sashForm);
		{
			Composite composite = new Composite(sashForm, SWT.BORDER);
			GridLayoutFactory.create(composite).noSpacing().noMargins()
					.columns(2);
			CLabel labelTitle = new CLabel(composite, SWT.NONE);
			labelTitle.setImage(DesignerPlugin
					.getImage("structure/components_view.gif"));
			labelTitle.setText("控件");
			GridDataFactory.create(labelTitle).alignVM();
			ToolBar toolbar = new ToolBar(composite, SWT.RIGHT);
			GridDataFactory.create(toolbar).alignHR().grabH();
			ToolItem tltmNewItem = new ToolItem(toolbar, SWT.NONE);
			tltmNewItem.setToolTipText("展开");
			tltmNewItem.setImage(DesignerPlugin.getImage("expand_all.gif"));
			tltmNewItem.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					UiUtils.expandAll(treeComponent);
				}
			});

			ToolItem tltmNewItem_1 = new ToolItem(toolbar, SWT.NONE);
			tltmNewItem_1.setToolTipText("折叠");
			tltmNewItem_1.setImage(DesignerPlugin.getImage("collapse_all.gif"));
			tltmNewItem_1.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					UiUtils.collapseAll(treeComponent);
				}
			});
			Label label = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
			GridDataFactory.create(label).spanH(2).fill().grabH();
			treeComponent = new Tree(composite, SWT.NONE);
			GridDataFactory.create(treeComponent).spanH(2).fill().grab();

			TreeItem trtmNewTreeitem = new TreeItem(treeComponent, SWT.NONE);
			trtmNewTreeitem.setText("输入固定值");
			trtmNewTreeitem.setImage(ResourceManager.getPluginImage(
					Activator.PLUGIN_ID, "icons/propertiesedit.gif"));
			treeComponent.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					ExecutionUtils.runRethrow(new RunnableEx() {
						public void run() throws Exception {
							buildPropertys();
						}
					});
				}
			});

		}
		{
			Composite composite = new Composite(sashForm, SWT.BORDER);
			GridLayoutFactory.create(composite).noSpacing().noMargins()
					.columns(2);
			CLabel labelTitle = new CLabel(composite, SWT.NONE);
			labelTitle.setImage(DesignerPlugin
					.getImage("structure/properties_view.gif"));
			labelTitle.setText("属性值");
			GridDataFactory.create(labelTitle).alignVM();
			ToolBar toolbar = new ToolBar(composite, SWT.RIGHT);
			GridDataFactory.create(toolbar).alignHR().grabH();
			final ToolItem tltmNewItem_2 = new ToolItem(toolbar, SWT.NONE);
			tltmNewItem_2.setText("指定参数类型");
			final Menu menu = new Menu(toolbar);
			// toolbar.setMenu(menu);
			SelectionListener typeListener = new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					MenuItem item = (MenuItem) e.widget;
					if (e.widget.getData() != null)
						tltmNewItem_2.setText(item.getText());
					else
						tltmNewItem_2.setText("指定参数类型");
					tltmNewItem_2.getParent().getParent().layout(true, true);
					type = (Class<?>) item.getData();
					format = (String) item.getData("format");
				}
			};

			MenuItem mntmNewCheckbox = new MenuItem(menu, SWT.RADIO);
			mntmNewCheckbox.setText("字符串");
			mntmNewCheckbox.setData(String.class);
			mntmNewCheckbox.addSelectionListener(typeListener);

			MenuItem mntmNewCheckbox_1 = new MenuItem(menu, SWT.RADIO);
			mntmNewCheckbox_1.setText("整型（Long）");
			mntmNewCheckbox_1.setData(Long.class);
			mntmNewCheckbox_1.addSelectionListener(typeListener);

			MenuItem mntmNewCheckbox_2 = new MenuItem(menu, SWT.RADIO);
			mntmNewCheckbox_2.setText("浮点型（Double）");
			mntmNewCheckbox_2.setData(Double.class);
			mntmNewCheckbox_2.addSelectionListener(typeListener);

			MenuItem mntmNewCheckbox_3 = new MenuItem(menu, SWT.RADIO);
			mntmNewCheckbox_3.setText("日期（yyyy-MM-dd）");
			mntmNewCheckbox_3.setData(Date.class);
			mntmNewCheckbox_3.setData("format", "yyyy-MM-dd");
			mntmNewCheckbox_3.addSelectionListener(typeListener);

			MenuItem mntmNewItem = new MenuItem(menu, SWT.RADIO);
			mntmNewItem.setText("日期时间(yyyy-MM-dd HH:mm:ss)");
			mntmNewItem.setData(Date.class);
			mntmNewItem.addSelectionListener(typeListener);
			mntmNewItem.setData("format", "yyyy-MM-dd HH:mm:ss");

			MenuItem mntmNewItem4 = new MenuItem(menu, SWT.RADIO);
			mntmNewItem4.setText("不指定类型");
			mntmNewItem4.setSelection(true);
			mntmNewItem4.addSelectionListener(typeListener);

			tltmNewItem_2.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					Rectangle b = tltmNewItem_2.getBounds();
					menu.setLocation(tltmNewItem_2.getParent().toDisplay(b.x,
							b.y + b.height));
					menu.setVisible(true);
				}
			});
			Label label = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
			GridDataFactory.create(label).spanH(2).fill().grabH();

			Composite composite_1 = new Composite(composite, SWT.NONE);
			GridDataFactory.create(composite_1).spanH(2).fill().grab();
			StackLayout stack = new StackLayout();
			composite_1.setLayout(stack);
			treeProperty = new Tree(composite_1, SWT.NONE);
			valueText = new Text(composite_1, SWT.NONE);
			valueText.setMessage("请输入参数值");
			stack.topControl = treeProperty;
			// composite_1.layout(true, true);
		}
		sashForm.setWeights(new int[] { 177, 264 });
		initializeData();
		return area;
	}

	/**
	 * Create contents of the button bar.
	 * 
	 * @param parent
	 */
	@Override
	protected void createButtonsForButtonBar(Composite parent) {
		Button button = createButton(parent, IDialogConstants.OK_ID,
				IDialogConstants.OK_LABEL, true);
		button.setText("确定");
		Button button_1 = createButton(parent, IDialogConstants.CANCEL_ID,
				IDialogConstants.CANCEL_LABEL, false);
		button_1.setText("取消");

	}

	private void initializeData() {
		if (root != null)
			buildComponent(null, root);
		UiUtils.expandAll(treeComponent);
	}

	// 构建组件树
	private void buildComponent(TreeItem parent, ObjectInfo info) {
		if (info.isRoot() || info instanceof WidgetInfo
				|| info instanceof NonVisualBeanContainerInfo
				|| info.getParent() instanceof NonVisualBeanContainerInfo) {
			// 过滤 未命名组件
			if (info instanceof WidgetInfo) {
				VariableSupport support = ((JavaInfo) info)
						.getVariableSupport();
				if (support == null || support.isDefault())
					return;
			}
			TreeItem item = parent == null ? new TreeItem(treeComponent,
					SWT.NONE) : new TreeItem(parent, SWT.NONE);
			item.setText(ObjectsLabelProvider.INSTANCE.getText(info));
			item.setImage(ObjectsLabelProvider.INSTANCE.getImage(info));
			item.setData(info);
			for (ObjectInfo c : info.getChildren()) {
				buildComponent(item, c);
			}
		}
	}

	// 构建组件属性
	private void buildPropertys() throws Exception {
		if (treeComponent.getSelectionCount() <= 0) {
			return;
		}
		treeProperty.removeAll();
		ObjectInfo model = (ObjectInfo) treeComponent.getSelection()[0]
				.getData();
		if (model instanceof DatasetInfo) {
			final DatasetInfo dataset = (DatasetInfo) model;
			// ======================
			// 初始化column
			// ======================
			if (!dataset.isInstantiationData()) {
				ExecutionUtils2.runErrorDlg("无法加载数据列", new RunnableEx() {
					public void run() throws Exception {
						dataset.updateData();
					}
				});
			}
			String[] columns = dataset.getDataColumns();
			if (columns != null) {
				for (String c : columns) {
					Class<?> type = dataset.getDataType(c);
					TreeItem item = new TreeItem(treeProperty, SWT.NONE);
					item.setText(c + " - " + type.getSimpleName());
					item.setData(c);
					item.setImage(TypeImageProvider.getImage(type));
				}
			}

			StackLayout stack = (StackLayout) treeProperty.getParent()
					.getLayout();
			if (stack.topControl != treeProperty) {
				stack.topControl = treeProperty;
				valueText.getParent().layout(true, true);
			}
		} else if (model instanceof JavaInfo) {
			ComponentDescription descr = ((JavaInfo) model).getDescription();
			Class<?> componentClass = descr.getComponentClass();
			for (String s : WIDGET_PROPERTIES_METHODS) {
				Method m = ReflectionUtils.getMethodByGenericSignature(
						componentClass, s);
				if (m != null && m.getReturnType() != null) {
					TreeItem item = new TreeItem(treeProperty, SWT.NONE);
					item.setText(s + " - " + m.getReturnType().getSimpleName());
					item.setData(m);
					item.setImage(TypeImageProvider.getImage(m.getReturnType()));
				}
			}
			// System.out.println(descr.getMethods());
			StackLayout stack = (StackLayout) treeProperty.getParent()
					.getLayout();
			if (stack.topControl != treeProperty) {
				stack.topControl = treeProperty;
				valueText.getParent().layout(true, true);
			}
		} else if (model == null) {
			StackLayout stack = (StackLayout) valueText.getParent().getLayout();
			if (stack.topControl != valueText) {
				stack.topControl = valueText;
				valueText.getParent().layout(true, true);
			}
			valueText.setFocus();
		}
	}

	@Override
	protected void okPressed() {
		StackLayout stack = (StackLayout) valueText.getParent().getLayout();
		if (stack.topControl == valueText) { // 输入固定值
			param = new Param();
			param.type = type == null ? String.class : type;
			param.format = format;
			try {
				param.value = convertToValue(valueText.getText(), param.type,
						param.format);
			} catch (Exception e) {
				String error = "'" + valueText.getText() + "'不是合法的"
						+ param.type.getSimpleName() + "值";
				MessageDialog.openError(getShell(), "操作错误", error);
				return;
			}
			super.okPressed();
		} else if (treeProperty.getSelectionCount() > 0) {
			JavaInfo c = (JavaInfo) treeComponent.getSelection()[0].getData();
			Object p = treeProperty.getSelection()[0].getData();
			param = new Param();
			param.type = type;
			param.format = format;
			if (c instanceof DatasetInfo && p instanceof String) {// p:数据集列名
				param.target = c;
				param.signature = "getValue(\"" + p + "\")";
			} else if (c instanceof JavaInfo && p instanceof Method) {// p:
																		// 控件获取值方法
				param.target = c;
				param.signature = ReflectionUtils
						.getMethodGenericSignature((Method) p);
			} else {
				return;
			}
			super.okPressed();
		} else {
			MessageDialog.openQuestion(getParentShell(), "提示", "选择为空!");
		}
	}

	/**
	 * Return the initial size of the dialog.
	 */
	@Override
	protected Point getInitialSize() {
		return new Point(598, 483);
	}

	@SuppressWarnings("unused")
	private Object convertToValue(String str, Class<?> type, String format)
			throws Exception {
		if (String.class.equals(type)) {
			return str;
		} else if (Long.class.equals(type)) {
			return Long.parseLong(str);
		} else if (Double.class.equals(type)) {
			return Double.parseDouble(str);
		} else if (Date.class.equals(type)) {
			SimpleDateFormat dateFormat = new SimpleDateFormat(format);
			return dateFormat.parse(str);
		}
		return null;
	}
}
